extends "res://kerno/fenestroj/tipo_a1.gd"
# форма маршрута


# uuid выполняемого проекта
var projekto_itineroj_uuid
var projekto_mouse # проект запущен мышкой

# основной список 
@onready var listo = get_node("VBox/body_texture/ItemList")

# если маршрут создаётся списком, то это новый проект
# если мышкой по космосу после мышки - меняем задачу на новую в том же проекте
# если мышкой по космосу после проекта (несколько задач в списке), то закрываем проект и открываем новый проект

# маршрут движения управляемого объекта (список проектов с задачей маршрута)
var itineroj = [] 
#uuid_tasko - uuid задачи, когда уже летим
#uuid_celo - uuid цели полёта, если это объект 
#nomo - название действия
# priskribo - описание действия + при наличии название объекта цели
# координаты цели полёта
#			'koordinatoX':
#			'koordinatoY':
#			'koordinatoZ':
# distance - расстояние до цели полёта
# pozicio - в какой позиции должна находится задача
# transform - transform координат цели движения (лучше высчитать один раз при добавлении)
# kategorio - категория задачи объекта

# маршрут стоит на паузе
var itinero_pause = true


# список id запросов, отправленных на сервер
var id_projekto = 0 # id запроса по созданию проекта
var id_taskoj = 0 # id запроса на список задач
var id_tasko = 0 # id запроса на одну задачу
var id_eniri_kosmostacio = 0 # id запроса на вход в станцию

func _ready():
	Global.fenestro_itinero = self
	print('установили fenestro_itinero', self)
	# подключаем сигнал для обработки входящих данных
	var err = Net.connect("input_data", Callable(self, "_on_data"))
	if err:
		print('error = ',err)


func _on_data():
	var i_data_server = 0
	var masivo_forigo = [] # массив индексов на удаление
	for on_data in Net.data_server:
		if int(on_data['id']) == id_projekto:
			# запустили новый проект
			taskoj_to_server(on_data['payload']['data'])
			masivo_forigo.insert(0, i_data_server) # удаляем после окончания цикла
			id_projekto = 0
		elif int(on_data['id']) == id_taskoj:
			# присвоить uuid задачам после ответа
			# uuid соответственно переданным задачам - по порядку
			var i = 0
			for datoj in on_data['payload']['data']['redaktuKreiTaskojTaskojPosedanto']['taskoj']:
				itineroj[i]['uuid_tasko'] = datoj['uuid']
				i += 1
			id_taskoj = 0
			masivo_forigo.insert(0, i_data_server) # удаляем после окончания цикла
		elif int(on_data['id']) == id_tasko:
			if Global.logs:
				print('===',on_data['payload']['data']['redaktuTaskojTasko'])
			itineroj.front()['uuid_tasko'] = on_data['payload']['data']['redaktuTaskojTasko']['taskoj']['uuid']
			id_tasko = 0
			masivo_forigo.insert(0, i_data_server) # удаляем после окончания цикла
		elif int(on_data['id']) == id_eniri_kosmostacio:
			# проверяем - разрешили войти или нет
			pass
			# если не разрешили - выводим сообщение
			pass
			id_eniri_kosmostacio = 0
			masivo_forigo.insert(0, i_data_server) # удаляем после окончания цикла
		i_data_server += 1
	for forigo in masivo_forigo:
		Net.data_server.remove(forigo)

var step = 0 #шаг времени для обновления расстояния

func _physics_process(delta):
	step += delta
	if step>1:
		step = 0
		if Global.fenestro_kosmo:
			distance_to(Global.fenestro_kosmo.get_node("ship").position)


# очистить список маршрута в окне маршрута
func purigi_fenestro():
	listo.clear()


# вывести на экран окна весь список маршрута с предварительным очищением окна
func FillItemList():
	purigi_fenestro()
	# Заполняет список маршрутом
	for Item in itineroj:
		listo.add_item('('+
			#String(int(Item['distance']))+') '+Item['priskribo'], null, true)
			str(Item['distance'])+') '+Item['priskribo'], null, true)


#пересчет дистанции до объектов в списке
func distance_to(trans):
	for obj in itineroj:
		if obj['koordinatoX']:
			obj['distance'] = trans.distance_to(Vector3(obj['koordinatoX'],
				obj['koordinatoY'],obj['koordinatoZ']))
	purigi_fenestro()
	FillItemList()


# начинаем маршрут
func komenci_itinero():
	if Global.fenestro_kosmo:
		# отправляем в полёт
		vojkomenco()#начинаем движение
		if !itinero_pause:
			#запускаем таймер
			$VBox/body_texture/HBoxContainer/kom_itinero.disabled=true


# начинаем лететь
func _on_kom_itinero_pressed():
	fenestro_supren()
	if Global.fenestro_kosmo:
		projekto_mouse = false # проект не по мышке
		#создать проект
		#создать список задач на основе списка itineroj
		komenci_itinero()


# ткнули мышкой в космосе, отправились к точке в космосе
# отправили к конкретному объекту mouse=false
# добавить задачу в маршрут, а при отсутствии проекта - создать маршрут из одной точки
func okazigi_itinero(uuid_celo, nomo, priskribo, koordinatoX, koordinatoY, 
	koordinatoZ, transform, distance, kategorio, mouse):
		# kategorio=Net.kategorio_movado
	if len(itineroj)>1:
		fermi_projekto_tasko()
	elif len(itineroj)>0:
		malmultigi_unua(mouse)
	if Global.fenestro_kosmo and koordinatoX:
		if !transform:
			transform = Transform3D(Basis.IDENTITY, Vector3(koordinatoX,
				koordinatoY, koordinatoZ))
		if (distance == -1):
			distance = Global.fenestro_kosmo.get_node("ship").position.distance_to(Vector3(koordinatoX,
				koordinatoY,koordinatoZ))
		Global.fenestro_kosmo.get_node("ship").target_rot = Quaternion(Global.fenestro_kosmo.get_node("ship").transform.looking_at(transform.origin,Vector3.UP).basis) #запоминаем в какое положение надо установить корабль, чтобы нос был к цели. Это в кватернионах. ХЗ что это, но именно так вращать правильнее всего.
	else:
		distance = 0
	add_itinero('', uuid_celo, nomo, priskribo, koordinatoX, 
		koordinatoY, koordinatoZ, transform, distance, 
		kategorio, -1)
	vojkomenco()


# добавить точку маршрута 
func add_itinero(uuid_tasko, uuid_celo, nomo, priskribo, koordinatoX, 
	koordinatoY, koordinatoZ, transform, distance, kategorio,
	pozicio):
	itineroj.append({
		'uuid_tasko':uuid_tasko,
		'uuid_celo':uuid_celo,
		'nomo':nomo,
		'priskribo':priskribo,
		'koordinatoX':koordinatoX,
		'koordinatoY':koordinatoY,
		'koordinatoZ':koordinatoZ,
		'transform': transform,
		'distance':distance,
		'kategorio':kategorio,
		'pozicio':pozicio
	})
	#listo.add_item('('+String(int(distance))+') '+priskribo, null, true)
	listo.add_item('('+ str(distance)+') '+priskribo, null, true)


# удаляем первую точку маршрута (выполнена)
# mouse - движение по мышке
func malmultigi_unua(mouse = false): # уменьшить первый
	# если первая точка задача с uuid - закрываем её
	# ставим задачу в "Закрыта" (Статус = 4)
	if itineroj.front()['uuid_tasko']:
# warning-ignore:unused_variable
		var id = Net.get_current_query_id()
		Net.net_id_clear.push_back(id)
		Net.send_json(Queries.finado_tasko(itineroj.front()['uuid_tasko'],Net.statuso_fermo,id))
	itineroj.pop_front()
#	а если это движение по мышке?? что бы продолжить тот же проект
	if mouse and projekto_mouse:
		FillItemList()
	elif len(itineroj)==0:# если была последняя точка, то закрываем проект
		fermi_projekto()
	else:
		FillItemList()


# закрываем проект
func fermi_projekto():
	if projekto_itineroj_uuid:
#		send_fermi_projekto(projekto_itineroj_uuid)
		projekto_itineroj_uuid = ''
		projekto_mouse = true
	malplenigi_itinero()


# очищаем данные проекта
func fermi_projekto_tasko():
	if projekto_itineroj_uuid:
		projekto_itineroj_uuid = ''
		projekto_mouse = true
	malplenigi_itinero()


# очищаем маршрут  clear_itinero
func malplenigi_itinero():
	itineroj.clear()
	itinero_pause = true
	FillItemList()
#	приводим кнопки в исходное состояние
	$VBox/body_texture/HBoxContainer/kom_itinero.disabled=false
	$VBox/body_texture/HBoxContainer/itinero_next.disabled=true
	$VBox/body_texture/HBoxContainer/itinero_fin.disabled=true
	$VBox/body_texture/HBoxContainer/itinero_clear.disabled=true
	$VBox/body_texture/HBoxContainer/itinero_fin.text='Пауза'


# поставить на паузу или отправить дальше
func _on_itinero_fin_pressed():
	fenestro_supren()
	if Global.fenestro_kosmo:
		if itinero_pause:
			server_statuso_tasko(Net.statuso_laboranta)
		else:
			server_statuso_tasko(Net.status_pauzo)


# кнопка сброса маршрута
func _on_itinero_clear_pressed():
	fenestro_supren()
	projekto_mouse = true
	if len(itineroj)==0:
		return 404
	if Global.fenestro_kosmo:
		#закрыть все задачи и проект
		server_fermi_projekto_tasko()


#отправляем на сервер запрос на закрытие текущей задачи и проекта
func server_fermi_projekto_tasko():
	if projekto_itineroj_uuid:
		if itineroj.front()['uuid_tasko']:
			Net.send_json(Queries.finado_projekto_tasko(projekto_itineroj_uuid,itineroj.front()['uuid_tasko']))
		else:
			Net.send_json(Queries.finado_projekto(projekto_itineroj_uuid))


#отправляем на сервер запрос на изменение статуса текущей задаче
func server_statuso_tasko(statuso):
	if projekto_itineroj_uuid:
		if itineroj.front()['uuid_tasko']:
			Net.send_json(Queries.finado_tasko(itineroj.front()['uuid_tasko'],statuso))


# пропустить текущую цель и лететь к следующей
func _on_itinero_next_pressed():
	fenestro_supren()
	# отправить на сервер закрытие текущей задачи
	if Global.fenestro_kosmo:
		if len(itineroj)==1:
			#если задача последняя, закрываем и проект
			server_fermi_projekto_tasko()
		else: 
			# закрываем задачу
			server_statuso_tasko(Net.statuso_fermo)


#передача данных на сервер при отправке корабля по первой цели
func vojkomenco(): # нача́ло доро́ги
	if len(itineroj)==0:
		return 404
	var koordinatoX = 0
	var koordinatoY = 0
	var koordinatoZ = 0
	if Global.fenestro_kosmo:
		koordinatoX = Global.fenestro_kosmo.get_node("ship").position.x
		koordinatoY = Global.fenestro_kosmo.get_node("ship").position.y
		koordinatoZ = Global.fenestro_kosmo.get_node("ship").position.z
	var q = Title.get_node("CanvasLayer/UI/UI/Taskoj").QueryObject.new()
	# отправляем на сервер маршрут
	if !projekto_itineroj_uuid:#если проекта нет, то создаём
		# создание проекта с задачами идёт в два этапа:
		# 1 - создаём запись проекта и получаем его uuid
		# 2- создаём задачи к проекту после ответа сервера
		# цель маршрута берём из itineroj
		id_projekto = Net.get_current_query_id()
		var count_itineroj=len(itineroj)-1
		Net.send_json(q.instalo_projekto(
			Global.direktebla_objekto[Global.realeco-2]['uuid'], # uuid объекта управления
			koordinatoX,
			koordinatoY,
			koordinatoZ,
			itineroj[count_itineroj]['koordinatoX'], #fin_koordX
			itineroj[count_itineroj]['koordinatoY'], #fin_koordY
			itineroj[count_itineroj]['koordinatoZ'], #fin_koordZ
			id_projekto
		))
	else:#проект есть, изменяем задачу
		# изменяем цель проекта
		var id = Net.get_current_query_id()
		if itineroj.front()['uuid_tasko']: # если есть uuid задачи
			print('===не реализовано')
#			Net.send_json(q.instalo_tasko_uuid_koord_json(
#				если задача зарегистрирована на сервере, то мы должны передать её uuid
#				itineroj.front()['uuid_tasko'], 
#				koordinatoX,
#				koordinatoY,
#				koordinatoZ,
#				2, # берём в работу
#				id
#			))
		else: #создаём новую задачу
			id_tasko = id
			itineroj.front()['uuid_tasko'] = id_tasko
			Net.send_json(q.instalo_tasko_koord(
	#			если задача зарегистрирована на сервере, то мы должны передать её uuid
				Global.direktebla_objekto[Global.realeco-2]['uuid'], 
				projekto_itineroj_uuid, 
				koordinatoX,
				koordinatoY,
				koordinatoZ,
				itineroj.front()['koordinatoX'], #fin_koordX
				itineroj.front()['koordinatoY'], #fin_koordY
				itineroj.front()['koordinatoZ'], #fin_koordZ
				id_tasko
			))
	blokado_butono()


# блокирование кнопок
func blokado_butono():
	get_node("VBox/body_texture/HBoxContainer/kom_itinero").disabled=true
	get_node("VBox/body_texture/HBoxContainer/itinero_next").disabled=false
	get_node("VBox/body_texture/HBoxContainer/itinero_fin").disabled=false
	get_node("VBox/body_texture/HBoxContainer/itinero_clear").disabled=false


# записав проект в базу, получили его uuid и теперь передаём на сервер его задачи
func taskoj_to_server(on_data):
	projekto_itineroj_uuid = on_data['redaktuTaskojProjekto']['projekto']['uuid']
	# теперь создаём задачу с координатами
	var q = Title.get_node("CanvasLayer/UI/UI/Taskoj").QueryObject.new()
	var ship = null
	if Global.fenestro_kosmo:
		ship = Global.fenestro_kosmo.get_node("ship")
		Global.direktebla_objekto[Global.realeco-2]['koordinatoX'] = ship.position.x
		Global.direktebla_objekto[Global.realeco-2]['koordinatoY'] = ship.position.y
		Global.direktebla_objekto[Global.realeco-2]['koordinatoZ'] = ship.position.z
		Global.direktebla_objekto[Global.realeco-2]['rotationX'] = ship.rotation.x
		Global.direktebla_objekto[Global.realeco-2]['rotationY'] = ship.rotation.y
		Global.direktebla_objekto[Global.realeco-2]['rotationZ'] = ship.rotation.z
	id_taskoj = Net.get_current_query_id()
	Net.send_json(q.instalo_tasko_posedanto_koord(
			Global.direktebla_objekto[Global.realeco-2]['uuid'], 
			projekto_itineroj_uuid, 
			Global.direktebla_objekto[Global.realeco-2]['koordinatoX'], #kom_koordX
			Global.direktebla_objekto[Global.realeco-2]['koordinatoY'], #kom_koordY
			Global.direktebla_objekto[Global.realeco-2]['koordinatoZ'], #kom_koordZ
			itineroj,
			id_taskoj
	))


# процесс входа в станцию
func eniri_kosmostacio(shipo_uuid):
	if Global.logs:
		print('=== пошел вход в станцию')
	# запрашиваем данные по станции
	Title.objekto_link(shipo_uuid)
	# отписываемся от событий в космосе
	Global.fenestro_kosmo.nuligo_subscribtion_kubo()
	# меняем сцену 
	Title.CloseWindow()
	Global.direktebla_objekto[Global.realeco-2]['kosmo'] = false
	Title.startigi_sceno()
	Title.reloadWindow()

	# warning-ignore:return_value_discarded
	get_tree().change_scene_to_file('res://blokoj/kosmostacioj/CapKosmostacio.tscn')
	# ставим подписку на события в станции


# Добавить блокировку кнопок управления маршрутом
# редактировать маршрут
# анализ пришедших задач
func sxangxi_itinero(projekto, tasko):
	if !Global.fenestro_kosmo: # если космос не загружен, то и маршрут не загружаем
		return false
	var sxipo = Global.fenestro_kosmo.get_node("ship")
	if tasko['statuso']['objId']==Net.statuso_fermo and\
			(Net.kategorio_eniri_kosmostacio==tasko['kategorio']['edges'].front()['node']['objId']): # закрытие задачи входа в станцию, осуществляем вход
		eniri_kosmostacio(Global.fenestro_kosmo.get_node("ship").uuid)
	var nomo = tasko['nomo']['enhavo']
	var priskribo = tasko['priskribo']['enhavo']
	var vector = 0
	if tasko['finKoordinatoX']:
		vector = Vector3(tasko['finKoordinatoX'],
			tasko['finKoordinatoY'], 
			tasko['finKoordinatoZ'])
	if projekto['uuid']==projekto_itineroj_uuid: # изменение по задаче в текущем проекте
		if projekto['statuso']['objId'] == Net.statuso_fermo:
			# закрытие проекта
			fermi_projekto_tasko()
			# очищаем маршрут у корабля
			sxipo.clear_route()
		var new_tasko = true # признак необходимости новой задачи
		var pos = 0 # номер позиции в списке задач
		var masivo_forigo = [] # массив индексов на удаление
		for it in itineroj:# проходим по всем задачам
			if tasko['uuid'] == String(it['uuid_tasko']): # нашли соответствующую задачу
				new_tasko = false
				if tasko['statuso']['objId']==Net.statuso_nova: # новая -  в очередь выполнения 
					it['koordinatoX'] = tasko['finKoordinatoX']
					it['koordinatoY'] = tasko['finKoordinatoY']
					it['koordinatoZ'] = tasko['finKoordinatoZ']
				elif tasko['statuso']['objId']==Net.statuso_laboranta: # в работе
					# задача должна быть первой в списке
					if pos: # если не первая
						masivo_forigo.insert(0, pos) # удаляем после окончания цикла
						itineroj.push_front({
							'uuid_tasko':tasko['uuid'],
							'koordinatoX':tasko['finKoordinatoX'],
							'koordinatoY':tasko['finKoordinatoY'],
							'koordinatoZ':tasko['finKoordinatoZ'],
							'uuid_celo':tasko['objekto']['uuid'] if tasko['objekto'] else '',
							'nomo': nomo,
							'priskribo': priskribo,
							'pozicio': tasko['pozicio'],
							'kategorio': tasko['kategorio']['edges'].front()['node']['objId'],
							'transform': Transform3D(Basis.IDENTITY, vector) if vector else Transform3D(Basis.IDENTITY),
							'distance': sxipo.position.distance_to(vector) if vector else 0
						})
					else:
						it['koordinatoX'] = tasko['finKoordinatoX']
						it['koordinatoY'] = tasko['finKoordinatoY']
						it['koordinatoZ'] = tasko['finKoordinatoZ']
					# отправляем корабль на уточнённые координаты, а точнее поворачиваем
					sxipo.rotate_start()
					itinero_pause = false
				elif tasko['statuso']['objId']==Net.statuso_fermo: # закрыта
					#удаляем из списка
					masivo_forigo.insert(0, pos) # удаляем после окончания цикла
					if len(itineroj)>0:
						sxipo.rotate_start()
				elif tasko['statuso']['objId']==Net.status_pauzo: # приостановлена
					itinero_pause = true
			pos += 1
		for forigo in masivo_forigo:
			itineroj.remove(forigo)
		if new_tasko: # добавляем новую задачу в проект
			if tasko['statuso']['objId']==Net.statuso_nova: # новая -  в очередь выполнения 
				# нужно выстроить по очерёдности
				pass
				pos = 0
				var pozicio = false
				for it in itineroj:# проходим по всем задачам и находим нужную позицию
					if it['pozicio']>tasko['pozicio']: # вставляем перед данной записью
						itineroj.insert(pos, {
							'uuid_tasko':tasko['uuid'],
							'koordinatoX': tasko['finKoordinatoX'],
							'koordinatoY': tasko['finKoordinatoY'],
							'koordinatoZ': tasko['finKoordinatoZ'],
							'pozicio': tasko['pozicio'],
							'uuid_celo':tasko['objekto']['uuid'] if tasko['objekto'] else '',
							'nomo': nomo,
							'priskribo': priskribo,
							'kategorio': tasko['kategorio']['edges'].front()['node']['objId'],
							'transform': Transform3D(Basis.IDENTITY, vector) if vector else Transform3D(Basis.IDENTITY),
							'distance': sxipo.position.distance_to(vector) if vector else 0
						})
						pozicio = true
						break
					pos += 1
				if !pozicio: # позиция не найдены, добавляем в конце
					itineroj.push_back({
						'uuid_tasko':tasko['uuid'],
						'koordinatoX': tasko['finKoordinatoX'],
						'koordinatoY': tasko['finKoordinatoY'],
						'koordinatoZ': tasko['finKoordinatoZ'],
						'pozicio': tasko['pozicio'],
						'uuid_celo':tasko['objekto']['uuid'] if tasko['objekto'] else '',
						'nomo': nomo,
						'priskribo': priskribo,
						'kategorio': tasko['kategorio']['edges'].front()['node']['objId'],
						'transform': Transform3D(Basis.IDENTITY, vector) if vector else Transform3D(Basis.IDENTITY),
						'distance': sxipo.position.distance_to(vector) if vector else 0
					})
			elif tasko['statuso']['objId']==Net.statuso_laboranta: # в работе
					# задача должна быть первой в списке
				itineroj.push_front({
					'uuid_tasko':tasko['uuid'],
					'koordinatoX':tasko['finKoordinatoX'],
					'koordinatoY':tasko['finKoordinatoY'],
					'koordinatoZ':tasko['finKoordinatoZ'],
					'pozicio': tasko['pozicio'],
					'uuid_celo':tasko['objekto']['uuid'] if tasko['objekto'] else '',
					'nomo': nomo,
					'priskribo': priskribo,
					'kategorio': tasko['kategorio']['edges'].front()['node']['objId'],
					'transform': Transform3D(Basis.IDENTITY, vector) if vector else Transform3D(Basis.IDENTITY),
					'distance': sxipo.position.distance_to(vector) if vector else 0
				})
					# отправляем корабль на уточнённые координаты, а точнее поворачиваем
				sxipo.rotate_start()
				itinero_pause = false
			elif tasko['statuso']['objId']==Net.status_pauzo: # приостановлена
				itineroj.push_front({
					'uuid_tasko':tasko['uuid'],
					'koordinatoX': tasko['finKoordinatoX'],
					'koordinatoY': tasko['finKoordinatoY'],
					'koordinatoZ': tasko['finKoordinatoZ'],
					'pozicio': tasko['pozicio'],
					'uuid_celo':tasko['objekto']['uuid'] if tasko['objekto'] else '',
					'nomo': nomo,
					'priskribo': priskribo,
					'kategorio': tasko['kategorio']['edges'].front()['node']['objId'],
					'transform': Transform3D(Basis.IDENTITY, vector) if vector else Transform3D(Basis.IDENTITY),
					'distance': sxipo.position.distance_to(vector) if vector else 0
				})
				itinero_pause = true
	else: # первая запись нового проекта
		if not(tasko['statuso']['objId']==Net.statuso_fermo):
			malplenigi_itinero()
			projekto_itineroj_uuid = projekto['uuid']
			itineroj.push_back({
				'uuid_tasko':tasko['uuid'],
				'koordinatoX': tasko['finKoordinatoX'],
				'koordinatoY': tasko['finKoordinatoY'],
				'koordinatoZ': tasko['finKoordinatoZ'],
				'pozicio': tasko['pozicio'],
				'uuid_celo':tasko['objekto']['uuid'] if tasko['objekto'] else '',
				'nomo': nomo,
				'priskribo': priskribo,
				'kategorio': tasko['kategorio']['edges'].front()['node']['objId'],
				'transform': Transform3D(Basis.IDENTITY, vector) if vector else Transform3D(Basis.IDENTITY),
				'distance': sxipo.position.distance_to(vector) if vector else 0
			})
			if tasko['statuso']['objId']==Net.statuso_laboranta: # в работе
				sxipo.rotate_start()
				itinero_pause = false
			else:
				itinero_pause = true
	if len(itineroj)>0:
		blokado_butono()
		if itinero_pause:
			#останавливаем движение корабля
			$VBox/body_texture/HBoxContainer/itinero_fin.text='Далее'
		else:
			$VBox/body_texture/HBoxContainer/itinero_fin.text='Пауза'


func _on_ItemList_focus_entered():
	fenestro_supren()



